package io.github.talelin.sleeve.common.utills;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.github.talelin.sleeve.mapper.FileTestMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 解析文件
 */
@Data
@Slf4j
@Component
public class ExcelListener extends AnalysisEventListener<Map<String, String>> {

    @Resource
    private FileTestMapper fileTestMapper;
    @Resource
    private JdbcUtil jdbcUtil;

    public ExcelListener() {
        super();
    }

    private final static Map<Integer,String> resultMap = new HashMap<>();

    static {
        resultMap.put(-1,"远程操作响应超时");
        resultMap.put(1,"远程操作成功");
        resultMap.put(2,"远程操作失败");
        resultMap.put(3,"未知返回类型");
    }

    /**
     * 每隔1000条存储数据库，然后清理list，方便内存回收
     */
    private static final int BATCH_COUNT = 1000;
    /**
     * 存放excel表的数据
     */
    private List<JSONObject> dataList = new ArrayList<>();


    private int columnNum = 0;
    private String tableName = "";
    private Map<Integer, String> indexType = new HashedMap(); //存放表第一行的字段
    private long start = 0;
    private long end = 0;

    private int checkFlag = 0;
    private String fileName = "";
    private Long dataNum = 0L; // 数据的行数
    private Long successNum = 0L;
    private Long failureNum = 0L;
    private List<JSONObject> failDataList = new ArrayList<>();
    private List<String> fieldCheck = new ArrayList<>(); //头部 属性

    /**
     * @Description: Excel的第一行
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        start = System.currentTimeMillis();
        log.debug("解析到一条头数据:{}", JSON.toJSONString(headMap));
        fieldCheck.clear();
        indexType.clear();
        tableName = this.fileName.replace(".xlsx", "");
        fieldCheck = fileTestMapper.getTableField(tableName);
        columnNum = headMap.size();
        for (int i = 0; i < columnNum; i++) {
            String typeName = headMap.get(i);
            indexType.put(i, typeName);
        }
        dataNum = 0L;
        successNum = 0L;
        failureNum = 0L;
        failDataList.clear();
    }
    /**
     * @Description:  遍历每一行(第二行开始)
     */
    @Override
    public void invoke(Map<String, String> data, AnalysisContext context) {
        int rowNum = context.readRowHolder().getRowIndex();
        log.debug("解析到第{}行的一条数据：{}", rowNum, JSON.toJSONString(data));
        dataNum++;
        JSONObject entityData = new JSONObject(true);
        for (int i = 0; i < columnNum; i++) {
            String value = data.get(i);
            entityData.put(indexType.get(i), value);
        }
        dataList.add(entityData);
        if (dataList.size() >= BATCH_COUNT) {
            log.debug("{}行数据解析完毕,开始插入数据库。", dataList.size());
            saveData();
        }
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        successNum = Long.valueOf(dataList.size());
        end = System.currentTimeMillis();
        log.info("Excel文件校验完成,耗时:{}", end - start);
        saveData();
        log.info("导入Excel文件:"+fileName+",成功"+successNum+"条，失败"+failureNum+"条");
    }

    /**
     * 加上存储数据库
     */
    private void saveData(){
        log.debug("{}条数据，开始存储数据库!", dataList.size());
        try {
            long time1 = System.currentTimeMillis();
            jdbcUtil.jdbcGeneralEntityImport(dataList, indexType, tableName);
            long time2 = System.currentTimeMillis();
            log.info("模板数据插入耗时：{}",(time2-time1));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        log.debug("存储数据库成功！");
        dataList.clear();
    }


}
